package com.molichuxing.gateway.bff.car.services.Impl;

import com.alibaba.fastjson.JSON;
import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.dto.TabDto;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.result.ResponseCodeEnum;
import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.CollectionUtils;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.DingTalkUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.gateway.bff.car.convertor.Convert;
import com.molichuxing.gateway.bff.car.entity.response.CarBasicVo;
import com.molichuxing.gateway.bff.car.entity.response.CarCheckVo;
import com.molichuxing.gateway.bff.car.entity.response.CheckVo;
import com.molichuxing.gateway.bff.car.entity.response.PdiCheckVo;
import com.molichuxing.gateway.bff.car.services.CarCheckBffService;
import com.molichuxing.gateway.property.CarCheckClientEnum;
import com.molichuxing.gateway.property.CarCheckInfoStatusEnum;
import com.molichuxing.gateway.utils.TokenUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.dto.request.modify.OrderReturnPdiModifyBizDto;
import com.molichuxing.services.business.dto.response.CarCheckDto;
import com.molichuxing.services.business.dto.response.VehicleNameBizDto;
import com.molichuxing.services.business.service.CarCheckBizService;
import com.molichuxing.services.business.service.OrderReturnBizService;
import com.molichuxing.services.business.service.VehicleBizService;
import com.molichuxing.services.infrastructure.dto.request.modify.CheckModifyDto;
import com.molichuxing.services.infrastructure.dto.request.modify.DisPdiCheckModifyDto;
import com.molichuxing.services.infrastructure.dto.request.modify.PdiCheckModifyDto;
import com.molichuxing.services.infrastructure.dto.response.*;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 车辆检验bff
 */
@Service("carCheckBffService")
public class CarCheckBffServiceImpl implements CarCheckBffService {


    private static final Logger logger = LoggerFactory.getLogger(CarCheckBffServiceImpl.class);

    @Resource
    private CarCheckBizService carCheckBizService;


    @Resource
    private CheckService checkService;

    @Resource
    private CarDetailService carDetailService;

    @Resource
    private VehicleService vehicleService;

    @Resource
    private VehicleColorService vehicleColorService;

    @Resource
    private VehicleModleService vehicleModleService;

    @Resource
    private VehicleMakeService vehicleMakeService;

    @Resource
    private CarService carService;

    @Resource
    private CheckImageService checkImageService;

    @Resource
    private CheckPreparationService checkPreparationService;

    @Resource
    private CheckDisputeService checkDisputeService;

    @Resource
    private StoreService storeService;
    @Resource
    private VehicleBizService vehicleBizService;
    @Resource
    private ContractService contractService;

    @Resource
    private IovCarService iovCarService;

    @Resource
    private TokenUtil tokenUtil;

    @Resource
    private OrderReturnBizService orderReturnBizService;

    @Resource
    private StockCarService stockCarService;

    @Value("${profiles.active.explain}")
    private String active;

    @Override
    public List<CarCheckVo> getCarCheckListByCarId(Integer carId) {
        List<CarCheckVo> result = Convert.toCarCheckVoList(carCheckBizService.getCheckByCarId(carId));
        if ((null == result) || (result.size() == 0)) {
            return null;
        }
        for (CarCheckVo carCheck : result) {
            if(null != carCheck.getCheckClient()) {
                if (carCheck.getCheckClient() == CarCheckClientEnum.MOLI.getValue()) {
                    carCheck.setOpName(CarCheckClientEnum.MOLI.getName() + "-" + carCheck.getOpName());
                } else if (carCheck.getCheckClient() == CarCheckClientEnum.DEALER.getValue()) {
                    carCheck.setOpName(CarCheckClientEnum.DEALER.getName() + "-" + carCheck.getOpName());
                }
            }
            if(null != carCheck.getReturnStoreId()) {
                try {
                    StoreDto storeDto = storeService.getStoreById(carCheck.getReturnStoreId());
                    if(null != storeDto) {
                        carCheck.setReturnStoreName(storeDto.getShortName());
                    }
                }catch(Exception e) {
                    logger.error("门店信息为空");
                }
            }
        }
        return result;
    }

    @Override
    public CarBasicVo getCheckBasicInfo(Integer checkId) throws Exception {
        CarBasicVo vo = new CarBasicVo();
        if (checkId == null) {
            return vo;
        }
        //根据检验id 获取 车辆id
        CheckDto checkDto = checkService.getById(checkId);
        if (checkDto == null) {
            return vo;
        }
        //车辆信息
        CarDto carDto = carService.getCarById(checkDto.getCarId());
        //车辆详情
        CarDetailDto carDetailDto = carDetailService.getCarDetailById(carDto.getId());

        //根据车型id 获取 车型相关信息
        VehicleDto vehicleDto = vehicleService.getVehicleByVehicleId(carDto.getVehicleId());
        //根据车型id 获取车系  获取子品牌名称
        VehicleMakeDto vehicleMakeDto = vehicleMakeService.getVehicleMakeDtoById(vehicleModleService.getVehicleModleDtoById(vehicleDto.getSeriesId()).getVehicleMakeId());
        //根据颜色id 获取车辆颜色
        VehicleColorDto vehicleColorDto = vehicleColorService.getVehicleColorByvehicleColorId(carDto.getVehicleColorId());
        vo.setColor(vehicleColorDto.getName());
        vo.setLicencePlate(carDto.getLicencePlate());
        vo.setVin(carDto.getVin());
        vo.setName(vehicleDto.getName());
        vo.setVehicleName(vehicleMakeDto.getName());
        vo.setYear(vehicleDto.getYear());
        vo.setStatus(CarCheckStatusEnum.getName(Integer.valueOf(checkDto.getStatus())));
        vo.setEngineCode(carDetailDto.getEngineCode());
        vo.setOrderCode(checkDto.getOrderCode());
        StoreDto storeDto = storeService.getStoreById(checkDto.getReturnStoreId());
        vo.setReturnStoreId(checkDto.getReturnStoreId());
        vo.setReturnStoreName(storeDto.getFullName());
        return vo;
    }

    @Override
    public PdiCheckVo getPdiCheckNewInfo(Integer checkId) throws Exception {
        PdiCheckVo vo = new PdiCheckVo();
        if (checkId != null) {
            CheckDto checkDto = checkService.getById(checkId);
            CheckDisputeDto checkDisputeDto = checkDisputeService.getByCheckId(checkId);
            if (checkDto != null) {
                vo = Convert.toPdiCheckVo(checkDto, checkDisputeDto);
                //查询还车单
                if (checkDto.getOrderCode() != null) {
                    List<ContractDto> contractByOrderCode = contractService.getContractByOrderCode(checkDto.getOrderCode(), ContractTypeEnum.MILEAGE_BAG_RETURN_CAR.getValue());
                    if (CollectionUtils.isNotEmpty(contractByOrderCode)) {
                        vo.setRelativePath(contractByOrderCode.get(0).getContractPath()); //还车单pdf地址
                    }
                }
                return vo;
            } else {
                return vo;
            }
        } else {
            return vo;
        }
    }

    @Override
    public CheckVo getCheckNewInfo(Integer checkId) throws Exception {
        CheckVo vo = new CheckVo();
        if (checkId != null) {
            CheckDto checkDto = checkService.getById(checkId);
            if (checkDto != null) {
                vo = Convert.toCheckVo(checkDto);

                // 车辆信息
                CarDto carDto = carService.getCarById(checkDto.getCarId());
                if (carDto != null) {

                    //获取车辆行驶里程
                    ResponseResult<Map<String, IovMileageDto>> iovMap = iovCarService.getMileageByVins(Arrays.asList(carDto.getVin()));
                    if (!iovMap.getCode().equals(0)) {
                        throw new BizException("获取当前已行驶里程失败");
                    }

                    if (iovMap.getData() != null && iovMap.getData().size() > 0) {
                        if (iovMap.getData().get(carDto.getVin()).getOdo() != null) {
                            vo.setMileage(new BigDecimal(String.valueOf(iovMap.getData().get(carDto.getVin()).getOdo())));
                        } else {
                            vo.setMileage(new BigDecimal("0"));
                        }
                    }
                }
                return vo;
            } else {
                return vo;
            }
        } else {
            return vo;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean checkCar(CheckModifyDto checkModifyDto) throws Exception {
        return carCheckBizService.checkCar(checkModifyDto);
    }

    /**
     * PDI检验列表信息
     *
     * @param selectParams
     * @return
     * @throws Exception
     */
    @Override
    public Paged<CarCheckVo> getPdiCarCheck(Map<String, Object> selectParams) throws Exception {
        Paged<CarCheckVo> carCheckVoPage = new Paged<CarCheckVo>();
        List<Integer> carIdsByOrderCode = new ArrayList<>();
        Integer dealerId = ObjectCastUtil.castInteger(selectParams.get("dealerId"));

        Paged<CarCheckDto> dto = carCheckBizService.getPdiCarCheck(ObjectCastUtil.castString(selectParams.get("licencePlate")), ObjectCastUtil.castString(selectParams.get("vin")),
                selectParams.get("orderCode") == null ? null : ObjectCastUtil.castLong(selectParams.get("orderCode")),
                ObjectCastUtil.castInteger(selectParams.get("returnStoreId")),
                selectParams.get("status") == null ? null : CarCheckStatusEnum.getEnum(ObjectCastUtil.castInt(selectParams.get("status"))),
                ObjectCastUtil.castInteger(selectParams.get("pageSize")) == null ? 10 : ObjectCastUtil.castInteger(selectParams.get("pageSize")),
                ObjectCastUtil.castInteger(selectParams.get("pageNum")) == null ? 1 : ObjectCastUtil.castInteger(selectParams.get("pageNum"))
                , dealerId);

        carCheckVoPage = Convert.toPagedCarCheckVo(dto);
        List<CarCheckVo> carCheckVoList = carCheckVoPage.getList();
        if (CollectionUtils.isNotEmpty(carCheckVoList)) {

            List<Long> orderCodeList = new ArrayList<>();
            List<Integer> vehicleIdList = new ArrayList<>();
            for (CarCheckVo carCheckVo : carCheckVoList) {
                StoreDto storeDto = storeService.getStoreById(carCheckVo.getReturnStoreId());
                carCheckVo.setReturnStoreId(storeDto.getStoreId());
                carCheckVo.setReturnStoreName(storeDto.getShortName());

                Integer vehicleId = carCheckVo.getVehicleId();
                vehicleIdList.add(vehicleId);

                orderCodeList.add(carCheckVo.getOrderCode());
            }

            //获取还车单
            Map<Long, List<ContractDto>> contractMapByOrderCode = null;
            if (CollectionUtils.isNotEmpty(orderCodeList)) {
                contractMapByOrderCode = contractService.getContractMapByOrderCode(orderCodeList, ContractTypeEnum.MILEAGE_BAG_RETURN_CAR.getValue()); //还车单对象集合
            }

            //获取车型
            List<Integer> carIds = getVehicleIds(carCheckVoList);
            Map<Integer, String> vehicleMap = null;
            if(null != carIds) {
                vehicleMap = vehicleBizService.getVehicleFullName(carIds);
            }

            for (CarCheckVo checkVo : carCheckVoList) {
                if (contractMapByOrderCode != null && contractMapByOrderCode.size() > 0) { //设置还车单地址pdf地址
                    List<ContractDto> contractDtoList = contractMapByOrderCode.get(checkVo.getOrderCode());
                    if (CollectionUtils.isNotEmpty(contractDtoList)) {
                        ContractDto contractDto = contractDtoList.get(0);
                        checkVo.setRelativePath(contractDto.getContractPath());
                    }
                }

                if (vehicleMap != null && vehicleMap.size() > 0) { //设置车型
                    checkVo.setVehicleName(vehicleMap.get(checkVo.getVehicleId()));
                }

                checkVo.setCarTypeStr(CarsTypeEnum.getName(checkVo.getCarType()));
            }
        }

        return getPageTab(carCheckVoPage, CarCheckTypeEnum.PDI.getValue(), dealerId);
    }

    private List<Integer> getVehicleIds(List<CarCheckVo> dataList) {
        List<Integer> vehicleIds = null;

        if (CollectionUtils.isNotEmpty(dataList)) {
            vehicleIds = new ArrayList<>();
            for(CarCheckVo vo: dataList) {
                vehicleIds.add(vo.getVehicleId());
            }
        }
        return vehicleIds;
    }

    /**
     * 获取分页tab值
     *
     * @return
     * @throws Exception
     */
    private Paged<CarCheckVo> getPageTab(Paged<CarCheckVo> paged, Integer type, Integer dealerId) throws Exception {
        Map<Integer, Integer> statusCountMap = checkService.getCheckCountByStatus(type, dealerId);
        Integer allCount = checkService.getCount(type, dealerId);
        List<TabDto> tabList = new ArrayList<>();
        for (CarCheckInfoStatusEnum carCheckInfoStatusEnum : CarCheckInfoStatusEnum.values()) {
            int value = carCheckInfoStatusEnum.getValue();
            String name = carCheckInfoStatusEnum.getName();
            Integer count = 0;
            if (CarCheckInfoStatusEnum.ALL.getValue() == value) {
                count = allCount;
            } else if (null != statusCountMap && statusCountMap.size() > 0) {
                count = statusCountMap.get(value);
            }

            if (null == count) {
                count = 0;
            }

            TabDto tabDto = new TabDto();
            tabDto.setName(name);
            tabDto.setType(value);
            tabDto.setCount(count);
            tabList.add(tabDto);
        }

        return paged.setTab(tabList);
    }

    @Override
    public Boolean discussPdiCheck(DisPdiCheckModifyDto disPdiCheckModifyDto) throws Exception {
        int num = checkDisputeService.modifyCheckDispute(disPdiCheckModifyDto.getCheckId(), disPdiCheckModifyDto.getDiscussLossFee(), disPdiCheckModifyDto.getRemark(), tokenUtil.getUser().getAccount());
        if (num > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean pdiCheckCar(PdiCheckModifyDto pdiCheckModifyDto) throws Exception {
        CheckDto check = checkService.getById(pdiCheckModifyDto.getCheckId());
        if (check.getStatus() != CarCheckStatusEnum.NO_CHECK.getValue()) { //只有待检验的车才能够检验
            throw new BizException(ResponseCodeEnum.UNKNOWN_ERROR.getCode(), "车辆必须是未检验状态才可以检验");
        }

        CarDto car = carService.getCarById(check.getCarId());
        if (car == null) {
            throw new BizException(ResponseCodeEnum.UNKNOWN_ERROR.getCode(), "车辆不存在");
        }

        if (check != null) {
            pdiCheckModifyDto.setOpName(tokenUtil.getUser().getRealName()); //操作人
            boolean checkCarResult = carCheckBizService.pdiCheckCar(pdiCheckModifyDto);
            if (checkCarResult) {

                //修改仓库车辆类型
                boolean carStatusResult = false;
                if(car.getVehicleType() == CarsTypeEnum.NEW_CAR.getValue()) { //如果是新车，不可运行
                    carStatusResult = stockCarService.modifyCarStatus(car.getId(), StockCarCarStatusEnum.NOT_RENT.getValue());
                } else { //如果是二手车，可运营
                    carStatusResult = stockCarService.modifyCarStatus(check.getCarId(), StockCarCarStatusEnum.RENTED.getValue());
                }

                if (carStatusResult) {
                    try {
                        UserEntity currentLoginUser = tokenUtil.getUser();
                        OrderReturnPdiModifyBizDto dto = new OrderReturnPdiModifyBizDto(); //pid检测成功后修改订单
                        dto.setOrderCode(check.getOrderCode());
                        dto.setDamageFee(pdiCheckModifyDto.getLossFee());
                        dto.setCheckId(currentLoginUser.getAccountId()); //检验人id
                        dto.setCheckName(currentLoginUser.getRealName()); //检验人姓名
                        Boolean modifyOrderResult = orderReturnBizService.modifyReturnPdi(dto);
                        if (modifyOrderResult == null || !modifyOrderResult) {
                            DingTalkUtil.exceptionSend(active + "pdi检验修改订单失败，checkId = " + check.getId() + "，orderCode=" + check.getOrderCode());
                            return false;
                        }
                        return true;
                    } catch (Exception e) {
                        DingTalkUtil.exceptionSend(active + "pdi检验修改订单失败，checkId = " + check.getId() + "，orderCode=" + check.getOrderCode());
                        throw new Exception(e.getMessage(), e);
                    }
                }
            }
        }
        return false;
    }
}
